home *** CD-ROM | disk | FTP | other *** search
- head 1.8;
- branch ;
- access ;
- symbols ;
- locks ; strict;
- comment @ * @;
-
-
- 1.8
- date 90.02.28.11.10.55; author brent; state Exp;
- branches ;
- next 1.7;
-
- 1.7
- date 89.06.29.16.24.23; author ouster; state Exp;
- branches ;
- next 1.6;
-
- 1.6
- date 89.06.15.15.09.37; author ouster; state Exp;
- branches ;
- next 1.5;
-
- 1.5
- date 89.06.03.16.47.26; author ouster; state Exp;
- branches ;
- next 1.4;
-
- 1.4
- date 89.06.02.13.38.39; author brent; state Exp;
- branches ;
- next 1.3;
-
- 1.3
- date 89.04.20.10.24.21; author ouster; state Exp;
- branches ;
- next 1.2;
-
- 1.2
- date 89.04.20.10.23.14; author ouster; state Exp;
- branches ;
- next 1.1;
-
- 1.1
- date 89.04.20.10.04.16; author ouster; state Exp;
- branches ;
- next ;
-
-
- desc
- @@
-
-
- 1.8
- log
- @Updated to new Td_ControlCooked interface
- @
- text
- @/*
- * ttyPdev.c --
- *
- * This file provides a bridge between the pdev and td modules to
- * produce a pseudo-device that behaves like a terminal.
- *
- * Copyright 1989 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/ttyPdev.c,v 1.7 89/06/29 16:24:23 ouster Exp Locker: brent $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <pdev.h>
- #include <status.h>
- #include <stdlib.h>
- #include <string.h>
- #include <td.h>
-
- /*
- * Library imports:
- */
-
- extern void panic();
-
- /*
- * One of the following structures is created for each call to
- * Td_CreatePdev:
- */
-
- typedef struct {
- Pdev_Token pdev; /* Token returned by Pdev_Open. */
- char *pdevName; /* Name of pseudo-device file
- * (malloc'ed). */
- Td_Terminal term; /* Token returned by Td_Create. */
- int selectState; /* Current select state of terminal;
- * a combination of FS_READABLE,
- * FS_WRITABLE, and FS_EXCEPTION. */
- } PdevTerm;
-
- /*
- * Forward declarations to procedures defined later in this file:
- */
-
- static int ChangeReady();
- static int CookedProc();
- static int PdevClose();
- static int PdevIoctl();
- static int PdevOpen();
- static int PdevRead();
- static int PdevWrite();
- static int SendSignal();
-
- /*
- *----------------------------------------------------------------------
- *
- * Td_CreatePdev --
- *
- * Create a terminal with a pseudo-device attached to it.
- *
- * Results:
- * The return value is a handle that may be passed to
- * Td_DeletePdev to close the pseudo-terminal. The Td_Terminal
- * token for the terminal gets stored at *termPtr, for the
- * caller's use in communicating with the terminal driver.
- * If a pseudo-device couldn't be opened, then the return value
- * is NULL and an error message is stored in pdev_ErrorMsg.
- *
- * Side effects:
- * A Td_Terminal is created with its "cooked" side attached
- * to a pseudo-device managed by this module. The caller
- * must use the Fs_Select facilities so that this module
- * gets callbacks from the Pdev library.
- *
- *----------------------------------------------------------------------
- */
-
- Td_Pdev
- Td_CreatePdev(name, realNamePtr, termPtr, rawProc, clientData)
- char *name; /* Name of file to use for pseudo-device. */
- char **realNamePtr; /* Where to store pointer to actual name
- * used. */
- Td_Terminal *termPtr; /* Token for the Td_Terminal gets written
- * here, if this is non-NULL. */
- int (*rawProc)(); /* Procedure for Td module to call to
- * handle control requests on raw side
- * of terminal. */
- ClientData clientData; /* Arbitrary data value to pass to rawProc. */
- {
- Pdev_CallBacks callbacks;
- register PdevTerm *ptPtr;
-
- ptPtr = (PdevTerm *) malloc(sizeof(PdevTerm));
- callbacks.open = PdevOpen;
- callbacks.read = PdevRead;
- callbacks.write = PdevWrite;
- callbacks.ioctl = PdevIoctl;
- callbacks.close = PdevClose;
- ptPtr->pdev = Pdev_Open(name, realNamePtr, 1000, 0,
- &callbacks, (ClientData) ptPtr);
- if (ptPtr->pdev == NULL) {
- free((char *) ptPtr);
- return (Td_Pdev) NULL;
- }
- if (realNamePtr != NULL) {
- name = *realNamePtr;
- }
- ptPtr->pdevName = malloc((unsigned) (strlen(name) + 1));
- strcpy(ptPtr->pdevName, name);
- ptPtr->term = Td_Create(1000, CookedProc, (ClientData) ptPtr,
- rawProc, clientData);
- ptPtr->selectState = FS_WRITABLE;
-
- if (termPtr != NULL) {
- *termPtr = ptPtr->term;
- }
- return (Td_Pdev) ptPtr;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Td_DeletePdev --
- *
- * Delete a pseudo-device and the Td_Terminal associated with it.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The memory and state associated with the pseudo device and
- * terminal are recycled. The pseudo-device file is destroyed,
- * if that is possible.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Td_DeletePdev(ttyPdev)
- Td_Pdev ttyPdev; /* Pseudo-terminal to destroy. */
- {
- register PdevTerm *ptPtr = (PdevTerm *) ttyPdev;
-
- /*
- * Close the terminal first, so that hangups can be sent to
- * processes.
- */
-
- Td_Delete(ptPtr->term);
- Pdev_Close(ptPtr->pdev);
- unlink(ptPtr->pdevName);
- free(ptPtr->pdevName);
- free((char *) ptPtr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * PdevOpen --
- *
- * This procedure is called back by the Pdev module whenever
- * a pseudo-terminal is being opened.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static int
- PdevOpen(ptPtr, newStream, readBuffer, flags, procID, hostID,
- uid, selectBitsPtr)
- register PdevTerm *ptPtr; /* Our information about the pdev. */
- Pdev_Stream *newStream; /* Service stream associated with the
- * new open. */
- char *readBuffer; /* Read buffer: not used here. */
- int flags; /* Flags from open kernel call (not used). */
- int procID; /* Process doing open (not used). */
- int hostID; /* Host where process is running (not used). */
- int uid; /* Effective user id of pid (not used). */
- int *selectBitsPtr; /* Store select state of new stream here. */
- {
- int result;
- Boolean true = TRUE;
- ReturnStatus status;
-
- newStream->clientData = (ClientData) ptPtr;
- result = Td_Open(ptPtr->term, &ptPtr->selectState);
- *selectBitsPtr = ptPtr->selectState;
- status = Fs_IOControl(newStream->streamID, IOC_PDEV_WRITE_BEHIND,
- sizeof(int), (Address) &true, 0, (Address) NULL);
- if (status != SUCCESS) {
- panic("PdevOpen couldn't enable write-behind: %s",
- Stat_GetMsg(status));
- }
- return result;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * PdevClose --
- *
- * This procedure is called back by the Pdev module when all of
- * the streams corresponding to one "open" on a pseudo-terminal
- * have now been closed.
- *
- * Results:
- * Always returns zero.
- *
- * Side effects:
- * State in the terminal is updated.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- PdevClose(streamPtr)
- Pdev_Stream *streamPtr; /* Service stream that is about to go away. */
- {
- Td_Close(((PdevTerm *) streamPtr->clientData)->term);
- return 0;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * PdevRead --
- *
- * This procedure is called back by the Pdev module whenever
- * a client tries to read the pseudo-device associated with
- * a terminal.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static int
- PdevRead(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
- Pdev_Stream *streamPtr; /* Service stream the client specified in its
- * kernel call. */
- Pdev_RWParam *readPtr; /* Read parameter block. Indicates size,
- * buffer, plus various IDs */
- Boolean *freeItPtr; /* Not used here. */
- int *selectBitsPtr; /* Store new select state of terminal here. */
- Pdev_Signal *sigPtr;
- {
- int result;
- register PdevTerm *ptPtr = (PdevTerm *) streamPtr->clientData;
-
- result = Td_GetCooked(ptPtr->term, readPtr->procID, readPtr->familyID,
- &readPtr->length, readPtr->buffer, &sigPtr->signal,
- &ptPtr->selectState);
- *selectBitsPtr = ptPtr->selectState;
- return result;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * PdevWrite --
- *
- * This procedure is called back by the Pdev module whenever
- * a client tries to write the pseudo-device associated with
- * a terminal. Note: these writes are always asynchronous.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static int
- PdevWrite(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
- Pdev_Stream *streamPtr; /* Service stream the client specified in its
- * kernel call. */
- int async; /* Non-zero means this is an asynchronous
- * write request (should always be TRUE). */
- Pdev_RWParam *writePtr; /* Write parameter block. Indicates size,
- * offset, and buffer, among other things */
- int *selectBitsPtr; /* Store new select state of terminal here. */
- Pdev_Signal *sigPtr; /* Signal to return, if any */
- {
- register PdevTerm *ptPtr = (PdevTerm *) streamPtr->clientData;
- int oldBits, result;
-
- oldBits = ptPtr->selectState;
- result = Td_PutCooked(ptPtr->term, &writePtr->length, writePtr->buffer,
- &sigPtr->signal, &ptPtr->selectState);
- if (ptPtr->selectState != oldBits) {
- Pdev_EnumStreams(ptPtr->pdev, ChangeReady,
- (ClientData) ptPtr->selectState);
- }
- *selectBitsPtr = ptPtr->selectState;
- return result;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * PdevIoctl --
- *
- * This procedure is called back by the Pdev module whenever
- * a client tries to issue an ioctl on the pseudo-device associated
- * with a terminal.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static int
- PdevIoctl(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
- Pdev_Stream *streamPtr; /* Service stream the client specified in its
- * kernel call. */
- Pdev_IOCParam *ioctlPtr; /* I/O control parameters */
- int *selectBitsPtr; /* Store new select state of terminal here. */
- Pdev_Signal *sigPtr; /* Returned signal, if any */
- {
- register PdevTerm *ptPtr = (PdevTerm *) streamPtr->clientData;
- int result;
-
- result = Td_ControlCooked(ptPtr->term, ioctlPtr->command,
- ioctlPtr->format,
- ioctlPtr->inBufSize, ioctlPtr->inBuffer,
- &ioctlPtr->outBufSize, ioctlPtr->outBuffer,
- &sigPtr->signal, &ptPtr->selectState);
- *selectBitsPtr = ptPtr->selectState;
- return result;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * CookedProc --
- *
- * This procedure is called back by the Td module to inform
- * us of various things happening on the cooked side of the
- * terminal.
- *
- * Results:
- * The return value is the number of bytes of output data
- * stored at outBuffer (always 0 right now).
- *
- * Side effects:
- * Depends on the command; read the code for details.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static int
- CookedProc(ptPtr, command, inSize, inBuffer, outSize, outBuffer)
- register PdevTerm *ptPtr; /* Information about the pseudo-device
- * for the terminal. */
- int command; /* Identifies control operation being
- * invoked, e.g. TD_COOKED_SIGNAL. */
- int inSize; /* Number of bytes of input data available
- * to us. */
- char *inBuffer; /* Pointer to input data. */
- int outSize; /* Maximum number of bytes of output data
- * we can return to caller. */
- char *outBuffer; /* Area in which to store output data for
- * caller. */
- {
- int result = 0;
-
- switch (command) {
- case TD_COOKED_SIGNAL:
- (void) Pdev_EnumStreams(ptPtr->pdev, SendSignal,
- (ClientData) inBuffer);
- break;
- case TD_COOKED_READS_OK:
- if (!(ptPtr->selectState & FS_READABLE)) {
- ptPtr->selectState |= FS_READABLE;
- (void) Pdev_EnumStreams(ptPtr->pdev, ChangeReady,
- (ClientData) ptPtr->selectState);
- }
- break;
- case TD_COOKED_WRITES_OK:
- if (!(ptPtr->selectState & FS_WRITABLE)) {
- ptPtr->selectState |= FS_WRITABLE;
- (void) Pdev_EnumStreams(ptPtr->pdev, ChangeReady,
- (ClientData) ptPtr->selectState);
- }
- break;
- }
- return result;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ChangeReady --
- *
- * This procedure is called back by Pdev_EnumStreams in order
- * to reset the readiness of all the streams associated with
- * a terminal.
- *
- * Results:
- * Always returns 0.
- *
- * Side effects:
- * The stream's select state is updated to match.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- ChangeReady(streamPtr, selectState)
- Pdev_Stream *streamPtr; /* Information about the particular
- * stream. */
- int selectState; /* New select state for stream. */
- {
- ReturnStatus status;
-
- status = Fs_IOControl(streamPtr->streamID, IOC_PDEV_READY,
- sizeof(int), (Address) &selectState, 0, (Address) 0);
- if (status != SUCCESS) {
- panic("ChangeReady couldn't reset select state for pdev: %s",
- Stat_GetMsg(status));
- }
- return 0;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * SendSignal --
- *
- * This procedure is called back by Pdev_EnumStreams in order
- * to send a signal to the controlling process for a terminal.
- *
- * Results:
- * Always returns 1 to abort the enumeration after 1 stream
- * has been processed (there's no need to generate the signal
- * more than once).
- *
- * Side effects:
- * A signal is sent to the pseudo-device's controlling process (group).
- *
- *----------------------------------------------------------------------
- */
-
- static int
- SendSignal(streamPtr, sigInfoPtr)
- Pdev_Stream *streamPtr; /* Information about the particular
- * stream. */
- Td_Signal *sigInfoPtr; /* Information about signal to send. */
- {
- ReturnStatus status;
- Pdev_Signal sigInfo;
-
- status = Compat_UnixSignalToSprite(sigInfoPtr->sigNum, &sigInfo.signal);
- if (status != SUCCESS) {
- panic("SendSignal couldn't translate signal %d", sigInfoPtr->sigNum);
- }
- sigInfo.code = 0;
-
- /*
- * Ignore errors in sending the signal: they could happen because
- * the user set a non-existent process group.
- */
-
- (void) Fs_IOControl(streamPtr->streamID, IOC_PDEV_SIGNAL_OWNER,
- sizeof(sigInfo), (Address) &sigInfo, 0, (Address) 0);
- return 1;
- }
- @
-
-
- 1.7
- log
- @Bogus extra parameter was causing selectBits to get garbaged in
- kernel and making txinfo hang, among other things.
- @
- text
- @d18 1
- a18 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/ttyPdev.c,v 1.6 89/06/15 15:09:37 ouster Exp $ SPRITE (Berkeley)";
- d350 1
- @
-
-
- 1.6
- log
- @Lint.
- @
- text
- @d18 1
- a18 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/ttyPdev.c,v 1.5 89/06/03 16:47:26 ouster Exp Locker: ouster $ SPRITE (Berkeley)";
- d312 1
- a312 1
- Pdev_EnumStreams(ptPtr->pdev, ChangeReady, &sigPtr->signal,
- @
-
-
- 1.5
- log
- @Several changes: TD_HANGUP is now TD_GOT_CARRIER and TD_LOST_CARRIER,
- added TD_RAW_BAUD_RATE callback, changed TD_COOKED_SIGNAL to provide
- both signal number and controlling process group.
- @
- text
- @d18 1
- a18 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/ttyPdev.c,v 1.4 89/06/02 13:38:39 brent Exp Locker: ouster $ SPRITE (Berkeley)";
- d265 1
- a265 1
- int result, sigNum;
- d347 1
- a347 1
- int result, sigNum;
- @
-
-
- 1.4
- log
- @Updated to new pseudo-device interface with signals
- @
- text
- @d18 1
- a18 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/ttyPdev.c,v 1.3 89/04/20 10:24:21 ouster Exp Locker: brent $ SPRITE (Berkeley)";
- d396 1
- a396 1
- (ClientData) *((int *) inBuffer));
- d471 1
- a471 1
- SendSignal(streamPtr, signal)
- d474 1
- a474 1
- int signal; /* Signal to send. */
- d479 1
- a479 1
- status = Compat_UnixSignalToSprite(signal, &sigInfo.signal);
- d481 1
- a481 1
- panic("SendSignal couldn't translate signal %d", signal);
- @
-
-
- 1.3
- log
- @Removed log code: no longer needed.
- @
- text
- @d18 1
- a18 1
- static char rcsid[] = "$Header: /a/newcmds/tty/RCS/ttyPdev.c,v 1.4 89/03/23 15:26:08 ouster Exp Locker: ouster $ SPRITE (Berkeley)";
- d256 1
- a256 2
- PdevRead(streamPtr, offset, procID, familyID, numBytesPtr, bufferPtr,
- freeItPtr, selectBitsPtr)
- d259 2
- a260 8
- int offset; /* Position within file; ignored. */
- int procID; /* Name of reading process. */
- int familyID; /* Process group to which procID belongs. */
- int *numBytesPtr; /* Points to number of bytes wanted;
- * overwritten with number of bytes actually
- * supplied. */
- char **bufferPtr; /* Pointer to pointer to buffer in which to
- * store data. */
- d263 1
- d268 3
- a270 5
- result = Td_GetCooked(ptPtr->term, procID, familyID, numBytesPtr,
- *bufferPtr, &sigNum, &ptPtr->selectState);
- if (sigNum != 0) {
- (void) kill(procID, sigNum);
- }
- d295 1
- a295 2
- PdevWrite(streamPtr, async, offset, procID, familyID, numBytesPtr,
- buffer, selectBitsPtr)
- d300 2
- a301 8
- int offset; /* Not used. */
- int procID; /* Not used. */
- int familyID; /* Not used. */
- int *numBytesPtr; /* Points to number of bytes the client wants
- * to write; overwritten with number of
- * bytes actually accepted. */
- char *buffer; /* Pointer to buffer containing data to be
- * be written. */
- d303 1
- d306 1
- a306 1
- int oldBits, result, sigNum;
- d309 2
- a310 5
- result = Td_PutCooked(ptPtr->term, numBytesPtr, buffer, &sigNum,
- &ptPtr->selectState);
- if (sigNum != 0) {
- (void) kill(procID, sigNum);
- }
- d312 1
- a312 1
- Pdev_EnumStreams(ptPtr->pdev, ChangeReady, &sigNum,
- d339 1
- a339 2
- PdevIoctl(streamPtr, command, procID, familyID, byteOrder, inSize, inBuffer,
- outSizePtr, outBuffer, selectBitsPtr)
- d342 1
- a342 14
- int command; /* Ioctl command (e.g. IOC_TTY_SETP). */
- int procID; /* Not used. */
- int familyID; /* Not used. */
- int byteOrder; /* Identifies data format of host on which
- * the client is running. */
- int inSize; /* Number of bytes of data in inBuffer. */
- char *inBuffer; /* Pointer to buffer containing input data
- * for ioctl. */
- int *outSizePtr; /* Pointer to maximum number of bytes of
- * output data wanted by client. Gets
- * overwritten with the amount supplied. */
- char *outBuffer; /* Pointer to buffer in which to store
- * output data. Guaranteed to have at
- * least *outSizePtr bytes of space. */
- d344 1
- d349 4
- a352 5
- result = Td_ControlCooked(ptPtr->term, command, inSize, inBuffer,
- outSizePtr, outBuffer, &sigNum, &ptPtr->selectState);
- if (sigNum != 0) {
- (void) kill(procID, sigNum);
- }
- @
-
-
- 1.2
- log
- @Slight improvement to tracing code.
- @
- text
- @a48 30
- * Temporary log to track down rlogin lock-up problem:
- */
-
- typedef struct {
- int operation; /* See #defines below. */
- int selectState;
- int otherData;
- } LogEntry;
-
- #define BEFORE_OPEN 1
- #define AFTER_OPEN 2
- #define BEFORE_READ 3
- #define AFTER_READ 4
- #define BEFORE_WRITE 5
- #define AFTER_WRITE 6
- #define BEFORE_IOCTL 7
- #define AFTER_IOCTL 8
- #define READS_OK 9
- #define WRITES_OK 10
-
- static LogEntry log[256];
- static int logCurrent;
-
- #define LOG(op, state, other) \
- log[logCurrent].operation = (op); \
- log[logCurrent].selectState = (state); \
- log[logCurrent].otherData = (other); \
- logCurrent = (logCurrent+1) & 0xff;
-
- /*
- a198 1
- LOG(BEFORE_OPEN, ptPtr->selectState, 0);
- a199 1
- LOG(AFTER_OPEN, ptPtr->selectState, result);
- a273 1
- LOG(BEFORE_READ, ptPtr->selectState, *numBytesPtr);
- a275 1
- LOG(AFTER_READ, ptPtr->selectState, result);
- a322 1
- LOG(BEFORE_WRITE, ptPtr->selectState, *numBytesPtr);
- a324 1
- LOG(AFTER_WRITE, ptPtr->selectState, result);
- a378 1
- LOG(BEFORE_IOCTL, ptPtr->selectState, command);
- a380 1
- LOG(AFTER_IOCTL, ptPtr->selectState, result);
- a429 1
- LOG(READS_OK, ptPtr->selectState, 0);
- a436 1
- LOG(WRITES_OK, ptPtr->selectState, 0);
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d468 1
- a472 1
- LOG(READS_OK, ptPtr->selectState, 0);
- d476 1
- a480 1
- LOG(WRITES_OK, ptPtr->selectState, 0);
- @
-